<template>
	<div
		data-testid="visualization"
		class="visualization"
		:class="{ 'visualization--ready': visualizationReady }"
	>
		<div class="label-scale d-flex">
			<div class="d-flex justify-content-start flex-grow-1">
				<LabelBar v-bind="labelBarProps('top', 'pvProduction')">
					<shopicon-regular-sun></shopicon-regular-sun>
				</LabelBar>
				<LabelBar v-bind="labelBarProps('top', 'batteryDischarge')">
					<BatteryIcon :soc="batterySoc" />
				</LabelBar>
				<LabelBar v-bind="labelBarProps('top', 'gridImport')">
					<shopicon-regular-powersupply></shopicon-regular-powersupply>
				</LabelBar>
				<LabelBar v-bind="labelBarProps('top', 'unknownImport')">
					<QuestionIcon />
				</LabelBar>
			</div>
			<div class="label-scale-name">In</div>
		</div>
		<div ref="site_progress" class="site-progress">
			<div class="site-progress-bar self-pv" :style="{ width: widthTotal(selfPvAdjusted) }">
				<AnimatedNumber
					v-if="selfPv && visualizationReady"
					class="power"
					:to="selfPv"
					:format="fmtBarValue"
				/>
			</div>
			<div
				class="site-progress-bar self-battery"
				:style="{ width: widthTotal(selfBatteryAdjusted) }"
			>
				<AnimatedNumber
					v-if="selfBattery && visualizationReady"
					class="power"
					:to="selfBattery"
					:format="fmtBarValue"
				/>
			</div>
			<div
				class="site-progress-bar grid-import"
				:style="{ width: widthTotal(gridImportAdjusted) }"
			>
				<AnimatedNumber
					v-if="gridImport && visualizationReady"
					class="power"
					:to="gridImport"
					:format="fmtBarValue"
				/>
			</div>
			<div
				class="site-progress-bar pv-export"
				:style="{ width: widthTotal(pvExportAdjusted) }"
			>
				<AnimatedNumber
					v-if="pvExport && visualizationReady"
					class="power"
					:to="pvExport"
					:format="fmtBarValue"
				/>
			</div>
			<div
				class="site-progress-bar unknown-power"
				:style="{ width: widthTotal(unknownPower) }"
			>
				<AnimatedNumber
					v-if="unknownPower && visualizationReady"
					class="power"
					:to="unknownPower"
					:format="fmtBarValue"
				/>
			</div>
			<div v-if="totalAdjusted <= 0" class="site-progress-bar w-100 grid-import">
				<span>{{ fmtW(0, POWER_UNIT.AUTO, true) }}</span>
			</div>
		</div>
		<div class="label-scale d-flex">
			<div class="d-flex justify-content-start flex-grow-1">
				<LabelBar v-bind="labelBarProps('bottom', 'homePower')">
					<shopicon-regular-home></shopicon-regular-home>
				</LabelBar>
				<LabelBar
					v-for="(lp, index) in loadpoints"
					:key="index"
					v-bind="labelBarProps('bottom', 'loadpoints', lp.power)"
				>
					<VehicleIcon :names="[lp.icon]" />
				</LabelBar>
				<LabelBar v-bind="labelBarProps('bottom', 'batteryCharge')">
					<BatteryIcon :soc="batterySoc" :gridCharge="batteryGridCharge" />
				</LabelBar>
				<LabelBar v-bind="labelBarProps('bottom', 'gridExport')">
					<shopicon-regular-powersupply></shopicon-regular-powersupply>
				</LabelBar>
				<LabelBar v-bind="labelBarProps('bottom', 'unknownOutput')">
					<QuestionIcon />
				</LabelBar>
			</div>
			<div class="label-scale-name">Out</div>
		</div>
		<BatteryIcon hold class="battery-hold" :class="{ 'battery-hold--active': batteryHold }" />
	</div>
</template>

<script>
import formatter, { POWER_UNIT } from "../../mixins/formatter";
import BatteryIcon from "./BatteryIcon.vue";
import LabelBar from "./LabelBar.vue";
import AnimatedNumber from "../AnimatedNumber.vue";
import VehicleIcon from "../VehicleIcon";
import QuestionIcon from "../MaterialIcon/Question.vue";
import "@h2d2/shopicons/es/regular/sun";
import "@h2d2/shopicons/es/regular/home";

export default {
	name: "Visualization",
	components: { BatteryIcon, LabelBar, AnimatedNumber, VehicleIcon, QuestionIcon },
	mixins: [formatter],
	props: {
		gridImport: { type: Number, default: 0 },
		selfPv: { type: Number, default: 0 },
		selfBattery: { type: Number, default: 0 },
		pvExport: { type: Number, default: 0 },
		loadpoints: { type: Array, default: () => [] },
		batteryCharge: { type: Number, default: 0 },
		batteryDischarge: { type: Number, default: 0 },
		batteryHold: { type: Boolean, default: false },
		batteryGridCharge: { type: Boolean, default: false },
		pvProduction: { type: Number, default: 0 },
		homePower: { type: Number, default: 0 },
		batterySoc: { type: Number, default: 0 },
		powerUnit: { type: String, default: POWER_UNIT.KW },
		inPower: { type: Number, default: 0 },
		outPower: { type: Number, default: 0 },
	},
	data: function () {
		return { width: 0 };
	},
	computed: {
		gridExport: function () {
			return this.applyThreshold(this.pvExport);
		},
		totalRaw: function () {
			return this.gridImport + this.selfPv + this.selfBattery + this.pvExport;
		},
		gridImportAdjusted: function () {
			return this.applyThreshold(this.gridImport);
		},
		selfPvAdjusted: function () {
			return this.applyThreshold(this.selfPv);
		},
		selfBatteryAdjusted: function () {
			return this.applyThreshold(this.selfBattery);
		},
		pvExportAdjusted: function () {
			return this.applyThreshold(this.pvExport);
		},
		totalAdjusted: function () {
			return (
				this.gridImportAdjusted +
				this.selfPvAdjusted +
				this.selfBatteryAdjusted +
				this.pvExportAdjusted
			);
		},
		unknownImport: function () {
			// input/output mismatch > 10%
			return this.applyThreshold(Math.max(0, this.outPower - this.inPower), 10);
		},
		unknownOutput: function () {
			// input/output mismatch > 10%
			return this.applyThreshold(Math.max(0, this.inPower - this.outPower), 10);
		},
		unknownPower: function () {
			if (this.unknownImport || this.unknownOutput) {
				const total = Math.max(this.inPower, this.outPower);
				return Math.abs(total - this.totalAdjusted);
			}
			return 0;
		},
		visualizationReady: function () {
			return this.totalAdjusted > 0 && this.width > 0;
		},
	},

	mounted: function () {
		this.$nextTick(function () {
			window.addEventListener("resize", this.updateElementWidth);
			this.updateElementWidth();
		});
	},
	beforeUnmount() {
		window.removeEventListener("resize", this.updateElementWidth);
	},
	methods: {
		widthTotal: function (power) {
			if (this.totalAdjusted === 0 || power === 0) return "0";
			return (100 / this.totalAdjusted) * power + "%";
		},
		fmtBarValue: function (watt) {
			if (!this.enoughSpaceForValue(watt)) {
				return "";
			}
			const withUnit = this.enoughSpaceForUnit(watt);
			return this.fmtW(watt, this.powerUnit, withUnit);
		},
		powerLabelAvailableSpace(power) {
			if (this.totalAdjusted === 0) return 0;
			const percent = (100 / this.totalAdjusted) * power;
			return (this.width / 100) * percent;
		},
		enoughSpaceForValue(power) {
			return this.powerLabelAvailableSpace(power) > 40;
		},
		enoughSpaceForUnit(power) {
			return this.powerLabelAvailableSpace(power) > 60;
		},
		hideLabelIcon(power, minWidth = 32) {
			if (this.totalAdjusted === 0) return true;
			const percent = (100 / this.totalAdjusted) * power;
			return (this.width / 100) * percent < minWidth;
		},
		applyThreshold(power, threshold = 2) {
			const percent = (100 / this.totalRaw) * power;
			return percent < threshold ? 0 : power;
		},
		updateElementWidth() {
			this.width = this.$refs.site_progress.getBoundingClientRect().width;
		},
		labelBarProps(position, name, val) {
			const value = val === undefined ? this[name] : val;
			const minWidth = 40;
			return {
				value,
				hideIcon: this.hideLabelIcon(value, minWidth),
				style: { "flex-basis": this.widthTotal(value) },
				[position]: true,
			};
		},
	},
};
</script>
<style scoped>
.site-progress {
	--height: 2.5rem;
	height: var(--height);
	border-radius: 10px;
	display: flex;
	overflow: hidden;
	margin-right: 1.2rem;
}
.label-scale-name {
	color: var(--evcc-gray);
	flex-basis: 1.2rem;
	flex-grow: 0;
	flex-shrink: 0;
	writing-mode: tb-rl;
	line-height: 1;
	text-align: center;
}
.site-progress-bar {
	display: flex;
	justify-content: center;
	align-items: center;
	overflow: hidden;
	position: relative;
	width: 0;
}
.visualization--ready .site-progress-bar {
	transition-property: width;
	transition-duration: var(--evcc-transition-medium);
	transition-timing-function: linear;
}
.grid-import {
	background-color: var(--evcc-grid);
	color: var(--bs-white);
}
html.dark .grid-import {
	color: var(--bs-dark);
}

.self-pv {
	background-color: var(--evcc-pv);
	color: var(--bs-dark);
}
.self-battery {
	background-color: var(--evcc-battery);
	color: var(--bs-dark);
}
.pv-export {
	background-color: var(--evcc-export);
	color: var(--bs-dark);
}
.unknown-power {
	background-color: var(--evcc-gray);
	color: var(--bs-dark);
}
.power {
	display: block;
	margin: 0 0.2rem;
	white-space: nowrap;
	overflow: hidden;
}
.visualization--ready :deep(.label-bar) {
	transition-property: flex-basis, opacity;
	transition-duration: var(--evcc-transition-medium), var(--evcc-transition-fast);
	transition-timing-function: linear, ease;
}
.visualization--ready :deep(.label-bar-icon) {
	transition-duration: var(--evcc-transition-very-fast), 500ms;
}
.battery-hold {
	position: absolute;
	top: 2.5rem;
	right: -0.25rem;
	color: var(--evcc-gray);
	opacity: 0;
	transition-property: opacity;
	transition-duration: var(--evcc-transition-medium);
	transition-timing-function: linear;
}
.battery-hold--active {
	opacity: 1;
}
</style>
